# 导入必要的库
import matplotlib.pyplot as plt  # 用于绘制图表
import numpy as np  # 用于数值运算
import pandas as pd  # 用于数据处理
import math  # 用于数学计算

def tem_curve(data):
    """温度曲线绘制"""
    date = list(data['日期'])  # 从数据中提取日期列表
    tem_low = list(data['最低气温'])  # 从数据中提取最低气温列表
    tem_high = list(data['最高气温'])  # 从数据中提取最高气温列表

    # 对缺失值进行前向填充（如果当天的气温数据缺失，则用前一天的数据替代）
    for i in range(0, 14):
        if math.isnan(tem_low[i]):
            tem_low[i] = tem_low[i - 1]
        if math.isnan(tem_high[i]):
            tem_high[i] = tem_high[i - 1]

    tem_high_ave = sum(tem_high) / 14  # 计算平均高温
    tem_low_ave = sum(tem_low) / 14  # 计算平均低温

    tem_max = max(tem_high)  # 找到最高温度
    tem_max_date = tem_high.index(tem_max)  # 确定最高温度对应的索引位置
    tem_min = min(tem_low)  # 找到最低温度
    tem_min_date = tem_low.index(tem_min)  # 确定最低温度对应的索引位置

    x = range(1, 15)  # 创建一个表示未来14天的x轴范围
    plt.figure(1)  # 创建一个新的图形窗口
    plt.plot(x, tem_high, color='red', label='高温')  # 绘制高温曲线，颜色为红色
    plt.scatter(x, tem_high, color='red')  # 在高温曲线上添加散点
    plt.plot(x, tem_low, color='blue', label='低温')  # 绘制低温曲线，颜色为蓝色
    plt.scatter(x, tem_low, color='blue')  # 在低温曲线上添加散点

    # 绘制平均温度虚线
    plt.plot([1, 15], [tem_high_ave, tem_high_ave], c='black', linestyle='--')
    plt.plot([1, 15], [tem_low_ave, tem_low_ave], c='black', linestyle='--')

    plt.legend()  # 添加图例
    # 在图表上标注最高和最低温度
    plt.text(tem_max_date + 0.15, tem_max + 0.15, str(tem_max), ha='center', va='bottom', fontsize=10.5)
    plt.text(tem_min_date + 0.15, tem_min + 0.15, str(tem_min), ha='center', va='bottom', fontsize=10.5)

    plt.xticks(x)  # 设置x轴刻度
    plt.title('未来14天高温低温变化曲线图')  # 设置图表标题
    plt.xlabel('未来天数/天')  # 设置x轴标签
    plt.ylabel('摄氏度/℃')  # 设置y轴标签
    plt.show()  # 显示图表

def change_wind(wind):
    """改变风向，将文本形式的风向转换为角度值"""
    wind_directions = {
        "北风": 90, "南风": 270, "西风": 180, "东风": 360,
        "东北风": 45, "西北风": 135, "西南风": 225, "东南风": 315
    }

    # 使用字典映射来简化风向到角度的转换逻辑
    for i in range(0, 14):
        wind[i] = wind_directions.get(wind[i], wind[i])  # 如果找不到对应的方向则保持原样
    return wind

def wind_radar(data):
    """风向雷达图"""
    wind1 = list(data['风向1'])  # 从数据中提取第一时段的风向
    wind2 = list(data['风向2'])  # 从数据中提取第二时段的风向
    wind_speed = list(data['风级'])  # 从数据中提取风速等级

    wind1 = change_wind(wind1)  # 转换第一时段的风向为角度
    wind2 = change_wind(wind2)  # 转换第二时段的风向为角度

    degs = np.arange(45, 361, 45)  # 定义8个方向的角度数组
    temp = []  # 用于存储每个方向的平均风速
    for deg in degs:
        speed = []  # 临时存储符合当前方向的风速
        for i in range(0, 14):
            if wind1[i] == deg or wind2[i] == deg:  # 如果任一风向匹配当前角度
                speed.append(wind_speed[i])  # 将该日的风速加入speed列表
        temp.append(sum(speed) / len(speed) if len(speed) > 0 else 0)  # 计算并添加平均风速

    N = 8  # 雷达图的扇区数量
    theta = np.arange(0. + np.pi / 8, 2 * np.pi + np.pi / 8, 2 * np.pi / 8)  # 定义雷达图的角度坐标
    radii = np.array(temp)  # 将平均风速转换为numpy数组作为极径
    colors = [(1 - x / max(temp), 1 - x / max(temp), 0.6) for x in radii]  # 根据风速设置颜色深浅

    plt.axes(polar=True)  # 创建极坐标系
    plt.bar(theta, radii, width=(2 * np.pi / N), bottom=0.0, color=colors)  # 绘制柱状图
    plt.title('未来14天风级图', x=0.2, fontsize=20)  # 设置图表标题
    plt.show()  # 显示图表

def weather_pie(data):
    """绘制天气饼图"""
    weather = list(data['天气'])  # 从数据中提取天气状况
    dic_wea = {}  # 创建空字典以统计每种天气出现的次数
    for i in range(0, 14):
        if weather[i] in dic_wea.keys():
            dic_wea[weather[i]] += 1  # 如果天气已经在字典中，计数加1
        else:
            dic_wea[weather[i]] = 1  # 如果天气不在字典中，初始化计数为1

    explode = [0.01] * len(dic_wea.keys())  # 设置所有扇区稍微分开
    color = ['lightskyblue', 'silver', 'yellow', 'salmon', 'grey', 'lime', 'gold', 'red', 'green', 'pink']  # 设置颜色列表
    plt.pie(dic_wea.values(), explode=explode, labels=dic_wea.keys(), autopct='%1.1f%%', colors=color)  # 绘制饼图
    plt.title('未来14天气候分布饼图')  # 设置图表标题
    plt.show()  # 显示图表

def main():
    plt.rcParams['font.sans-serif'] = ['SimHei']  # 解决中文显示问题，设置字体为黑体
    plt.rcParams['axes.unicode_minus'] = False  # 解决负号显示问题
    data14 = pd.read_csv('weather14.csv', encoding='gb2312')  # 读取CSV文件中的天气数据
    print(data14)  # 打印数据，以便查看
    tem_curve(data14)  # 调用函数绘制温度曲线
    wind_radar(data14)  # 调用函数绘制风向雷达图
    weather_pie(data14)  # 调用函数绘制天气饼图

if __name__ == '__main__':
    main()  # 当脚本被直接运行时，调用main函数